<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\App\WorkContact\Logic;

use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use MoChat\App\Corp\Contract\CorpContract;
use MoChat\App\WorkContact\Constants\Field\Status;
use MoChat\App\WorkContact\Constants\Gender;
use MoChat\App\WorkContact\Contract\ContactFieldContract;
use MoChat\App\WorkContact\Contract\ContactFieldPivotContract;
use MoChat\App\WorkContact\Contract\WorkContactContract;
use MoChat\App\WorkContact\Contract\WorkContactEmployeeContract;
use MoChat\App\WorkContact\Contract\WorkContactRoomContract;
use MoChat\App\WorkContact\Contract\WorkContactTagContract;
use MoChat\App\WorkContact\Contract\WorkContactTagGroupContract;
use MoChat\App\WorkContact\Contract\WorkContactTagPivotContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use MoChat\App\WorkRoom\Contract\WorkRoomContract;
use MoChat\Plugin\ContactEmployeeTag\Contract\ContactEmployeeTagContract;
use MoChat\Plugin\ContactStage\Contract\ContactStageContract;
use MoChat\Plugin\WorkMoment\Contract\WorkMomentCommentContract;

/**
 * 查看客户详情基本信息.
 *
 * Class ShowLogic
 */
class ShowLogic
{
    /**
     * @Inject
     * @var ContactStageContract
     */
    protected $contactStageService;

    /**
     * 客户表.
     * @Inject
     * @var WorkContactContract
     */
    private $contact;

    /**
     * 员工 - 客户关联.
     * @Inject
     * @var WorkContactEmployeeContract
     */
    private $contactEmployee;

    /**
     * 客户 - 标签关联.
     * @Inject
     * @var WorkContactTagPivotContract
     */
    private $contactTagPivot;

    /**
     * 标签.
     * @Inject
     * @var WorkContactTagContract
     */
    private $contactTag;

    /**
     * 客户群.
     * @Inject
     * @var WorkRoomContract
     */
    private $room;

    /**
     * 客户 - 客户群关联.
     * @Inject
     * @var WorkContactRoomContract
     */
    private $contactRoom;

    /**
     * 员工.
     * @Inject
     * @var WorkEmployeeContract
     */
    private $employee;

    /**
     * 企业表.
     * @Inject
     * @var CorpContract
     */
    private $corp;

    /**
     * @Inject
     * @var ContactEmployeeTagContract
     */
    private $contactEmployeeTagService;

    /**
     * 客户标签组.
     * @Inject
     * @var WorkContactTagGroupContract
     */
    private $workContactTagGroupContract;

    /**
     * 客户朋友圈的互动数据表.
     * @Inject
     * @var WorkMomentCommentContract
     */
    private $workMomentCommentService;

    /**
     * @Inject
     * @var ContactFieldPivotContract
     */
    private $contactFieldPivot;

    /**
     * @Inject
     * @var ContactFieldContract
     */
    private $contactField;

    /**
     * 客户id.
     * @var int
     */
    private $contactId;

    /**
     * 企业id.
     * @var int
     */
    private $corpId;

    /**
     * 员工id.
     * @var int
     */
    private $employeeId;

    public function handle(array $params): array
    {
        $this->contactId = (int) $params['contactId'];
        $this->corpId = $params['corpId'];
        $this->employeeId = $params['employeeId'];

        $columns = [
            'id',
            'wx_external_userid',
            'name',
            'avatar',
            'gender',
            'business_no',
            'follow_up_status',
        ];
        // 查询客户基础信息
        $contactInfo = $this->contact->getWorkContactByIdWithTrashed((int) $this->contactId, $columns);

        // 查询员工对客户的备注、描述
        $contactEmployee = $this->contactEmployee
            ->findWorkContactEmployeeByOtherIds($params['employeeId'], $this->contactId, ['remark', 'description', 'create_time'], true);

        // 查询客户企业标签
        $contactCorpTag = $this->getContactCorpTag($params['employeeId']);

        // 查询客户个人标签
        $contactEmployeeTag = $this->getContactEmployeeTag($this->contactId, (int) $params['employeeId']);

        // 查询客户所在群
        $roomName = $this->getContactRoom();

        // 查询客户归属企业成员
        $employees = $this->getEmployee();

        // 查询客户资料
        $fieldPivot = $this->getFieldPivot();

        // 朋友圈数据
        $moment = $this->getMoment();

        $followStageList = $this->contactStageService->getContactStagesByCorpId($this->corpId, ['id', 'name']);
        $phones=Db::table('work_contact_employee')->where('contact_id',$this->contactId)->where('employee_id',$params['employeeId'])->value('remark_mobiles');
        $phones=$phones?json_decode($phones,true):[];
        $pivotClient = Db::table('client_contact_pivot as pivot')
            ->join('client as client', 'client.id', '=', 'pivot.client_id')
            ->where('pivot.contact_id', $this->contactId)->select([
                'client.enterprise_name as enterpriseName',
                'pivot.created_at',
            ])->get();
        $pivotClient=empty($pivotClient)?[]:$pivotClient->toArray();
        return [
            'phone'=>!empty($phones)?reset($phones):'',
            'contactId' => (int) $contactInfo['id'],
            'wxExternalUserid' => $contactInfo['wxExternalUserid'] ?? '',
            'name' => $contactInfo['name'] ?? '',
            'avatar' => isset($contactInfo['avatar']) ? file_full_url($contactInfo['avatar']) : '',
            'gender' => $contactInfo['gender'] ?? 0,
            'genderText' => isset($contactInfo['gender']) ? Gender::getMessage($contactInfo['gender']) : '未知',
            'businessNo' => $contactInfo['businessNo'] ?? '',
            'remark' => $contactEmployee['remark'] ?? '',
            'description' => $contactEmployee['description'] ?? '',
            'fieldPivot' => $fieldPivot,
            'followUpStatus' => $this->getFollowUpStatus($followStageList, (int) $contactInfo['followUpStatus']),
            'createTime' => isset($contactEmployee['createTime']) ? substr($contactEmployee['createTime'], 0, 10) : '',
            'contactCorpTag' => $contactCorpTag,
            'contactEmployeeTag' => $contactEmployeeTag,
            'roomName' => $roomName,
            'employees' => $this->handleEmployee($employees),
            'addEmployees' => $employees,
            'employeeCount' => count($employees),
            'moment' => $moment,
            'followUpStatusList' => $followStageList, // 客户阶段管理
            'pivotClient'=>$pivotClient
        ];
    }

    /**
     * 客户阶段管理.
     */
    public function getFollowUpStatus(array $followStageList, int $followUpStatus): string
    {
        if (empty($followStageList)) {
            return '';
        }
        $state = [];
        foreach ($followStageList as $v) {
            $state[$v['id']] = $v['name'];
        }
        return $state[$followUpStatus] ?? '';
    }

    /**
     * 朋友圈.
     */
    protected function getMoment(): array
    {
        $comment['likeNumber'] = $this->workMomentCommentService->countWorkMomentCommentByContactId($this->contactId, 1);
        $comment['commentNumber'] = $this->workMomentCommentService->countWorkMomentCommentByContactId($this->contactId, 2);
        return $comment;
    }

    /**
     * 获取客户员工个人标签.
     */
    protected function getContactEmployeeTag(int $contactId, int $employeeId): array
    {
        return $this->contactEmployeeTagService->getContactEmployeeTagsByContactIdEmployeeId($contactId, $employeeId, ['id', 'name']);
    }

    protected function getFieldPivot(): array
    {
        // 查询所有开启的高级属性
        $fieldInfo = $this->contactField->getContactFieldsByStatusOrderByOrder($this->corpId, (int) Status::EXHIBITION, 1, ['id', 'label', 'type']);

        if (empty($fieldInfo)) {
            return [];
        }

        $fieldIds = array_column($fieldInfo, 'id');

        // 查询客户用户画像
        $info = $this->contactFieldPivot->getContactFieldPivotsByOtherId((int) $this->contactId, $fieldIds, ['id', 'contact_field_id', 'value']);
        if (! empty($info)) {
            $info = array_column($info, null, 'contactFieldId');
            foreach ($fieldInfo as &$item) {
                $item['contactFieldId'] = $item['id'];
                $item['contactFieldPivotId'] = empty($info[$item['id']]) ? '' : $info[$item['id']]['id'];
                $item['value'] = empty($info[$item['id']]) ? '' : $info[$item['id']]['value'];
            }
        } else {
            array_walk($fieldInfo, function (&$item) {
                $item['contactFieldId'] = $item['id'];
                $item['contactFieldPivotId'] = '';
                $item['value'] = '';
            });
        }
        return $fieldInfo;
    }

    private function handleEmployee(array $employees): array
    {
        if ((int) $this->employeeId === 0) {
            return $employees;
        }

        // 查询客户归属企业成员
        $contactEmployee = $this->contactEmployee->getWorkContactEmployeeByOtherId((int) $this->employeeId, (int) $this->contactId, ['employee_id', 'create_time', 'add_way', 'last_message_time']);

        if (empty($contactEmployee)) {
            return [];
        }
        // 根据员工id查询员工姓名
        $employeeInfo = $this->employee->getWorkEmployeeById($contactEmployee['employeeId'], ['id', 'wx_user_id', 'name', 'avatar', 'corp_id']);

        if (empty($employeeInfo)) {
            return [];
        }

        $contactEmployee['employeeName'] = $employeeInfo['name'];
        $contactEmployee['corpId'] = $employeeInfo['corpId'];
        $contactEmployee['wxUserId'] = $employeeInfo['wxUserId'];
        $contactEmployee['avatar'] = file_full_url($employeeInfo['avatar']);
        $contactEmployee['addWay'] = ['未知来源', '扫描二维码', '搜索手机号', '名片分享', '群聊', '手机通讯录', '微信联系人', '来自微信的添加好友申请', '安装第三方应用时自动添加的客服人员', '搜索邮箱', '部成员共享', '管理员/负责人分配'][$contactEmployee['addWay']] ?? '其他渠道';

        return [$contactEmployee];
    }

    /**
     * 获取客户所在群.
     * @return array
     */
    private function getContactRoom()
    {
        $contactRoom = $this->contactRoom->getWorkContactRoomsByContactId($this->contactId, ['employee_id', 'room_id', 'join_time']);
        if (empty($contactRoom)) {
            return [];
        }

        $roomIds = array_column($contactRoom, 'roomId');
        // 根据群id查询群名称
        $rooms = $this->room->getWorkRoomsById($roomIds, ['id', 'name', 'owner_id', 'created_at']);
        $data = [];
        foreach ($contactRoom as $item) {
            $data[$item['roomId']] = $item['joinTime'];
        }
        foreach ($rooms as $k => $v) {
            $employeeRoom = $this->contactRoom->getWorkContactRoomsByRoomIdEmployee($v['id'], ['employee_id']);
            $employeeIds = array_column($employeeRoom, 'employeeId');
            $employee = $this->employee->getWorkEmployeeById($v['ownerId'], ['name']);
            $rooms[$k]['ownerName'] = $employee['name'] ?? '';
            $rooms[$k]['joinTime'] = $data[$v['id']];
            $rooms[$k]['isJoin'] = in_array($this->employeeId, $employeeIds, true) ? 1 : 0;
        }
        return $rooms;
    }

    /**
     * 获取客户标签.
     * @param mixed $employeeId
     * @return array
     */
    private function getContactCorpTag($employeeId)
    {
        $contactTag = $employeeId > 0 ? $this->contactTagPivot->getWorkContactTagPivotsByOtherId($this->contactId, $employeeId, ['contact_tag_id']) : $this->contactTagPivot->getWorkContactTagPivotsByContactId($this->contactId, ['contact_tag_id']);
        if (empty($contactTag)) {
            return [];
        }

        $tagIds = array_column($contactTag, 'contactTagId');
        // 根据标签id查询标签名称
        $tagInfo = $this->contactTag->getWorkContactTagsById($tagIds, ['id', 'name', 'contact_tag_group_id']);

        if (empty($tagInfo)) {
            return [];
        }
        $tagGroupIds = array_column($tagInfo, 'contactTagGroupId');
        $tagGroup = $this->workContactTagGroupContract->getWorkContactTagGroupsById($tagGroupIds, ['id', 'group_name']);
        foreach ($tagGroup as $k => $v) {
            $info = $this->contactTag->getWorkContactTagsByGroupIdIds($v['id'], $tagIds, ['id', 'name', 'wx_contact_tag_id', 'contact_tag_group_id']);
            array_walk($info, function (&$item) {
                $item['tagId'] = $item['id'];
                $item['tagName'] = $item['name'];

                unset($item['id'], $item['name']);
            });
            $tagGroup[$k]['tags'] = $info;
        }

        return $tagGroup;
    }

    /**
     * 获取客户归属企业成员.
     * @return array
     */
    private function getEmployee()
    {
        // 查询客户归属企业成员
        $contactEmployee = $this->contactEmployee->getWorkContactEmployeesByContactId((int) $this->contactId, ['employee_id', 'create_time', 'add_way', 'last_message_time']);

        if (empty($contactEmployee)) {
            return [];
        }

        $employeeIds = array_column($contactEmployee, 'employeeId');
        // 根据员工id查询员工姓名
        $employeeInfo = $this->employee->getWorkEmployeesById($employeeIds, ['id', 'wx_user_id', 'name', 'avatar', 'corp_id']);

        if (empty($employeeInfo)) {
            return [];
        }

        $employeeInfo = array_column($employeeInfo, null, 'id');
        foreach ($contactEmployee as $k => $raw) {
            if (isset($employeeInfo[$raw['employeeId']])) {
                $contactEmployee[$k]['employeeName'] = $employeeInfo[$raw['employeeId']]['name'];
                $contactEmployee[$k]['corpId'] = $employeeInfo[$raw['employeeId']]['corpId'];
                $contactEmployee[$k]['wxUserId'] = $employeeInfo[$raw['employeeId']]['wxUserId'];
                $contactEmployee[$k]['avatar'] = file_full_url($employeeInfo[$raw['employeeId']]['avatar']);
                $contactEmployee[$k]['addWay'] = ['未知来源', '扫描二维码', '搜索手机号', '名片分享', '群聊', '手机通讯录', '微信联系人', '来自微信的添加好友申请', '安装第三方应用时自动添加的客服人员', '搜索邮箱', '部成员共享', '管理员/负责人分配'][$raw['addWay']] ?? '其他渠道';
            } else {
                unset($contactEmployee[$k]);
            }
        }
        $contactEmployee = array_merge($contactEmployee);
        $corpIds = array_unique(array_column($employeeInfo, 'corpId'));

        // 查询企业名称
        $corpInfo = $this->corp->getCorpsById($corpIds, ['id', 'name']);
        if (! empty($corpInfo)) {
            $corpInfo = array_column($corpInfo, null, 'id');

            foreach ($contactEmployee as &$val) {
                if (isset($corpInfo[$val['corpId']])) {
                    $val['corpName'] = $corpInfo[$val['corpId']]['name'];
                }
            }
            unset($val);
        }
        foreach ($contactEmployee as $k => $v) {
            $contactEmployee[$k]['corpEmployeeName'] = $v['corpName'] . ' ' . $v['employeeName'];
        }
        return $this->arraySort($contactEmployee, 'createTime', 'desc');
    }

    /**
     * 二维数组排列.
     * @param $array
     * @param $keys
     * @return array
     */
    private function arraySort($array, $keys, string $sort = 'asc')
    {
        $newArr = $valArr = [];
        foreach ($array as $key => $value) {
            $valArr[$key] = $value[$keys];
        }
        ($sort === 'asc') ? asort($valArr) : arsort($valArr);
        reset($valArr);
        foreach ($valArr as $key => $value) {
            $newArr[$key] = $array[$key];
        }
        return array_merge($newArr);
    }
}
